package service

import (
	"sync"
	"time"

	"gitee.com/liumou_site/disk-monitoring/backend/internal/model"
	"gitee.com/liumou_site/disk-monitoring/backend/internal/utils"
	"github.com/shirou/gopsutil/v3/disk"
)

// 用于存储上次IO统计的全局变量和互斥锁
var (
	lastIOCounters map[string]disk.IOCountersStat
	lastIOTime     time.Time
	ioMutex        sync.Mutex
)

// DiskService 磁盘服务接口
type DiskService interface {
	// GetDiskInfo 获取磁盘基本信息
	GetDiskInfo() ([]*model.DiskInfo, error)

	// GetDiskIOStats 获取磁盘IO统计信息
	GetDiskIOStats() ([]*model.DiskIOStat, error)

	// GetRealTimeDiskIOData 获取实时磁盘IO数据
	GetRealTimeDiskIOData() (*model.RealTimeDiskIOData, error)
}

// diskService 磁盘服务实现
type diskService struct {
	// 可以包含依赖的其他服务或数据访问对象
}

// NewDiskService 创建磁盘服务实例
func NewDiskService() DiskService {
	// 初始化上次IO统计信息
	lastIOCounters, _ = disk.IOCounters()
	lastIOTime = time.Now()

	return &diskService{}
}

// GetDiskInfo 获取磁盘基本信息
func (s *diskService) GetDiskInfo() ([]*model.DiskInfo, error) {
	partitions, err := disk.Partitions(true)
	if err != nil {
		return nil, err
	}

	var diskInfos []*model.DiskInfo
	for _, partition := range partitions {
		usage, err := disk.Usage(partition.Mountpoint)
		if err != nil {
			continue
		}

		diskInfo := &model.DiskInfo{
			Name:       partition.Device,
			Total:      utils.FormatBytes(usage.Total),
			Used:       utils.FormatBytes(usage.Used),
			Free:       utils.FormatBytes(usage.Free),
			UsageRate:  usage.UsedPercent,
			MountPoint: partition.Mountpoint,
			FileSystem: partition.Fstype,
		}

		diskInfos = append(diskInfos, diskInfo)
	}

	return diskInfos, nil
}

// GetDiskIOStats 获取磁盘IO统计信息
func (s *diskService) GetDiskIOStats() ([]*model.DiskIOStat, error) {
	ioCounters, err := disk.IOCounters()
	if err != nil {
		return nil, err
	}

	var diskIOStats []*model.DiskIOStat
	for name, counter := range ioCounters {
		diskIOStat := &model.DiskIOStat{
			Name:           name,
			ReadCount:      utils.FormatCount(counter.ReadCount),
			WriteCount:     utils.FormatCount(counter.WriteCount),
			ReadBytes:      utils.FormatBytes(counter.ReadBytes),
			WriteBytes:     utils.FormatBytes(counter.WriteBytes),
			IOPSInProgress: counter.IopsInProgress,
			IOTime:         utils.FormatLatency(float64(counter.IoTime)),
			WeightedIO:     utils.FormatLatency(float64(counter.WeightedIO)),
		}

		diskIOStats = append(diskIOStats, diskIOStat)
	}

	return diskIOStats, nil
}

// GetRealTimeDiskIOData 获取实时磁盘IO数据（包含IOPS和延迟）
func (s *diskService) GetRealTimeDiskIOData() (*model.RealTimeDiskIOData, error) {
	ioMutex.Lock()
	defer ioMutex.Unlock()

	currentIOCounters, err := disk.IOCounters()
	if err != nil {
		return nil, err
	}

	currentTime := time.Now()
	timeElapsed := currentTime.Sub(lastIOTime).Seconds()

	var diskIOStats []model.RealTimeDiskIOStat
	for name, counter := range currentIOCounters {
		readSpeed := float64(0)
		writeSpeed := float64(0)
		readIOPS := uint64(0)
		writeIOPS := uint64(0)
		readLatency := float64(0)
		writeLatency := float64(0)

		// 计算速度和IOPS
		if lastCounter, exists := lastIOCounters[name]; exists && timeElapsed > 0 {
			// 速度计算
			readBytesDiff := counter.ReadBytes - lastCounter.ReadBytes
			writeBytesDiff := counter.WriteBytes - lastCounter.WriteBytes

			readSpeed = float64(readBytesDiff) / timeElapsed
			writeSpeed = float64(writeBytesDiff) / timeElapsed

			// IOPS计算
			readCountDiff := counter.ReadCount - lastCounter.ReadCount
			writeCountDiff := counter.WriteCount - lastCounter.WriteCount

			readIOPS = uint64(float64(readCountDiff) / timeElapsed)
			writeIOPS = uint64(float64(writeCountDiff) / timeElapsed)

			// 延迟计算（如果有操作发生）
			if readCountDiff > 0 {
				readTimeDiff := counter.ReadTime - lastCounter.ReadTime
				readLatency = float64(readTimeDiff) / float64(readCountDiff)
			}

			if writeCountDiff > 0 {
				writeTimeDiff := counter.WriteTime - lastCounter.WriteTime
				writeLatency = float64(writeTimeDiff) / float64(writeCountDiff)
			}
		}

		// 格式化速度显示
		readSpeedStr := utils.FormatSpeed(readSpeed)
		writeSpeedStr := utils.FormatSpeed(writeSpeed)

		// 格式化延迟显示
		readLatencyStr := utils.FormatLatency(readLatency)
		writeLatencyStr := utils.FormatLatency(writeLatency)

		diskIOStat := model.RealTimeDiskIOStat{
			Name:         name,
			ReadSpeed:    readSpeedStr,
			WriteSpeed:   writeSpeedStr,
			ReadIOPS:     readIOPS,
			WriteIOPS:    writeIOPS,
			ReadLatency:  readLatencyStr,
			WriteLatency: writeLatencyStr,
			ReadCount:    counter.ReadCount,
			WriteCount:   counter.WriteCount,
		}

		diskIOStats = append(diskIOStats, diskIOStat)
	}

	// 更新上次统计信息
	lastIOCounters = currentIOCounters
	lastIOTime = currentTime

	realTimeData := &model.RealTimeDiskIOData{
		Timestamp:   currentTime.Unix(),
		DiskIOStats: diskIOStats,
	}

	return realTimeData, nil
}
